///
///  - [Event Sourcing with Aggregates in Rust](https://medium.com/capital-one-tech/event-sourcing-with-aggregates-in-rust-4022af41cf67)
///   The aggregate is a domain-driven-design (DDD) concept that fits well within event sourcing.
///  To put it as briefly as possible: you apply a **command** to an **aggregate** which then produces
/// **one or more events**. An aggregate can populate (re-hydrate) its state by sequential application of an event stream.
///
///  **Why are there no Domain Commands in DDD?**
///
///   Commands are typically the result of a user action. Inside the domain we don’t have user actions, therefor we don’t need commands.
///  Instead we have events which can help us react to things that have happened in the domain as a result of a user action outside the domain.
///
///   A user clicks on a button and a command is send. When a CommandHandler receives a command, it can create a new aggregate,
///  or make an aggregate by fetching the necessary data from persistence and invoke a method on the aggregate.
///  The invoked methods can emit events.
///
pub trait Aggregate {
  type ID;
  /// domain event e.g. TaskEvent
  type ItemEvent;
  /// snapshot entity e.g. TaskDBO
  type Snapshot;
  /// configuration for the aggregate
  type Config;

  /// initialize aggreate with snapshot data : snapshot and events,   
  /// initialize a ProductAggregate , typically after loading data from db
  fn init(snapshot: &Self::Snapshot, events: &Vec<Self::ItemEvent>, config:&Self::Config) -> Self
  where
    Self: Sized;

  /// apply an event:  f(state`1 + event) = state`2
  fn apply(&self, evt: &Self::ItemEvent) -> Self
  where
    Self: Sized;

  fn get_id(&self) -> &Self::ID;
  /// get latest snapshot after applying events
  fn get_snapshot(&self) -> &Self::Snapshot;
}
